package fatboy.test;

import java.util.List;
import java.util.Random;

import org.junit.Test;

import fatboy.hypeerweb.Connection;
import fatboy.hypeerweb.Node;
import junit.framework.Assert;

public class JamesBlackBoxTesting {

	/**
	 * The following tests cover remove with a web of size 1,2,3,4, 46, 64 nodes
	 * This is done to test boundary testing. These tests also test removing from the
	 * 0 node and a random node to help with that boundary testing. The smallest case
	 * that can be tested is a 1 node web, hence our start, and then 2,3,4 are for those
	 * cube cases near the minimum and also testing changes between cubes and non-cubes
	 * 46 and 64 are used to test the "way out there" test
	 * 
	 * Equivalence classes are also being tested. The classes are the single, 2 node, 4 node
	 * and 64 node hypeerwebs to test webs with no pointers, and the transitions between due to remove
	 * Nodes of 3 and 46 test the outside cases where there are edge/surrogate pointers to
	 * consider. In these tests, for the 1 node test it is the 0 node only being removed. The 2 node test
	 * I cover removing both nodes, with 3 and 4 I test the inbetweens with pointer cases and the 4 node
	 * to test transitions from a last node to an incomplete hypeerweb
	 * The final equivalence class is the 46 and 64 node webs that I test removing half of the nodes
	 * to test various cases removing end nodes, edge nodes, surrogate nodes, starting
	 * from a incomplete and complete hypeerweb
	 */
	@Test
	public void singleNodeRemove(){
		System.out.println("Testing remove with one node");
		Connection connect = new Connection();
		connect.addNode(0);	//Creation of single node web
		
		try{
			connect.removeNode(connect.getMyConnection());	//Testing remove on single node
		}
		catch(junit.framework.AssertionFailedError e){
			System.out.println("cannot remove last node");	//Catching error
		}
		
	}
	
	/**
	 * Testing web with 2 nodes
	 * (Boundry Value Testing)
	 * Testing ability to remove root and change value of root node
	 */
	@Test
	public void webWithTwoNodes(){
		System.out.println("\nTesting 2 nodes");
		Connection connect = new Connection();
		connect.addNode(0);
		connect.addNode(1);
		Node temp = connect.getAllNodes().get(1);
		Node temp2 = connect.getAllNodes().get(0);
		connect.removeNode(connect.getMyConnection());
		Assert.assertTrue(connect.getMyConnection().equals(temp));
		
		temp = connect.addNode(0);
		connect.removeNode(connect.getMyConnection());
		Assert.assertTrue(connect.getMyConnection().equals(temp));
		
		//Verify I cannot remove a non-existant node
		connect.removeNode(temp2);
	}
	
	/**
	 * Testing web with 3 and 4 nodes
	 * (Boundry Value Testing/Equivalence Classes)
	 * Testing a 4 node hypeerweb
	 * Testing small hypeerweb case
	 */
	@Test
	public void testWebNodes(){
		System.out.println("\nTesting 3 & 4 nodes");
		Connection connect = new Connection();
		connect.addNode(0);
		connect.addNode(1);
		connect.addNode(2);
		Node temp = connect.getAllNodes().get(1);
		connect.removeNode(connect.getMyConnection());
		Assert.assertTrue(connect.getAllNodes().size() == 2);
		
		connect.addNode(1);
		temp = connect.addNode(0);
		Assert.assertTrue(connect.getAllNodes().size()==4);
	}
	
	/**
	 * Testing a full web with 46 nodes
	 * (Boundry Value Testing & Equivalence Partitioning)
	 * remove in order
	 */
	
	private static int ODD = 46;
	@Test
	public void oddCube(){
		Connection connect = new Connection();
		Node temp = null;
		for(int i = 0; i<CUBE; i++){
			temp = connect.addNode(i);
		}
		List<Node> webList = connect.getAllNodes();
		Assert.assertTrue(webList.size()==CUBE);
		for(int i = 0; i<CUBE/2; i++){
			connect.removeNode(webList.get(i));
		}
		Assert.assertTrue(connect.getAllNodes().size() == CUBE/2);
		Assert.assertTrue(connect.getMyConnection().equals(temp));
	}
	
	/**
	 * Testing a full web with 64 nodes
	 * Equivalence Partitioning testing a full scale HypeerWeb
	 * with remove.
	 * Chooses half the nodes at random to remove
	 * 
	 * Expected: works
	 */
	
	private static int CUBE = 64;
	@Test
	public void testPerfectNode(){
		Connection connect = new Connection();
		Node temp = null;
		//add 64 nodes
		for(int i = 0; i<CUBE; i++){
			temp = connect.addNode(i);
		}
		
		List<Node> webList = connect.getAllNodes();
		Assert.assertTrue(webList.size()==CUBE);
		Random random = new Random();
		//randomly remove half the nodes
		for(int i = 0; i<CUBE/2; i++){
			connect.removeNode(connect.getAllNodes().get(random.nextInt(CUBE-i)));
		}
		Assert.assertTrue(connect.getAllNodes().size() == CUBE/2);
		//Assert.assertTrue(connect.getMyConnection().equals(temp));
	}
}
